/**
 * Creates the editor with editing area and toolbar.
 *
 * @author Lucian CIOROGA
 */
Editor = new Class({
    /**
     * Constructor.
     * @param {Object} options
     *
     * Options are:
     * 		buttons		The list of buttons that will be displayed. If this option is not set, the Editor will use a default list.
     */
    initialize: function(options){
        this.options = options;
        
        this.frame = new Element('iframe', {
            'styles': {
                'border': '1px solid #ccc',
                'background-color': '#fff',
				'margin-top': '1px'
            }
        });
    },
    
    /**
     * @return	The list of buttons (in order) that will be displayed in the toolbar.
     */
    getButtons: function(){
        if (this.options && this.options.buttons) {
            return this.options.buttons();
        } else {
            return [ButtonsFactory.B(), ButtonsFactory.I(), ButtonsFactory.U(), ButtonsFactory.JL(), ButtonsFactory.JC(), ButtonsFactory.JR(), ButtonsFactory.S(), ButtonsFactory.OL(), ButtonsFactory.UL(), ButtonsFactory.S(), ButtonsFactory.FS(), ButtonsFactory.FF(), ButtonsFactory.S(), ButtonsFactory.FG(), ButtonsFactory.BG()];
        }
    },
    
    /**
     * @param {Element} container	The DOM element given where the editor should be added.
     * 								Make sure that the <code>container</code> is loaded when the editor is rendered.
     */
    render: function(container){
        this.container = container;
        
        this.container.setStyle('background-color', '#f5f5f5');
        this.container.setStyle('border', '1px solid #ccc');
        this.container.setStyle('padding', '1px 1px 1px 1px');
		this.container.setStyle('float', 'left');
        
        var editor = this;
        var buttons = this.getButtons();
        
        // building toolbar table
        this.toolbar = new Element('div', {
            'styles': {
                'height': '20px'
            }
        });
        
        // creating toolbar
        $each(buttons, function(button){
            var borderStyle;
            if (button instanceof Separator) {
                borderStyle = 'none';
            } else {
                borderStyle = '1px solid #ccc';
            }
            
            var buttonContainer = new Element('div', {
                'styles': {
                    'float': 'left',
                    'border': borderStyle,
                    'height': '19px',
                    'margin': '0px 1px 0px 0px'
                }
            });
            
            var component = button.render(editor);
            buttonContainer.adopt(component);
            editor.toolbar.adopt(buttonContainer);
        });
        
        this.container.adopt(this.toolbar);
        this.container.adopt(this.frame);
        
        if (!window.ie) {
            // fix dimension problems
            var containerCoordinates = this.container.getCoordinates();
            var frameCoordinates = this.frame.getCoordinates();
            
            var verticalDiff = frameCoordinates.bottom - containerCoordinates.bottom;
            var horizontalDiff = frameCoordinates.right - containerCoordinates.right;
            
            this.frame.setStyle('width', frameCoordinates.width - horizontalDiff - 4);
            this.frame.setStyle('height', frameCoordinates.height - verticalDiff - 4);
        }
        
        // setting designMode = ON
        this.frame.addEvent('load', function(){
            if (window.opera || window.ie) {
                editor.content = this.contentWindow.document;
            } else if (window.gecko || window.webkit420) {
                editor.content = this.contentDocument;
            }
            
            if (editor.content != null) {
                if (window.ie) {
                    $(editor.content.body).setStyle('border', 'none');
                }
                
                editor.content.designMode = "on";
                
                // storing selection
                // IE hack
				if (window.ie) {
					$(editor.content.body).addEvent('click', function(){
						editor.lastSelection = editor.content.selection.createRange();
					});
					$(editor.content.body).addEvent('dblclick', function(){
						editor.lastSelection = editor.content.selection.createRange();
					});
				}
                
                // Checks if the user tried to set a value while the editor was not yet loaded.
                // If there is value stored, initializes the editor with the stored value.
                if (editor.value != null) {
                    editor.setValue(editor.value);
                }
            } else {
                editor.container.appendHTML("Unknown browser. Could not load editor.");
            }
        });
        
        if (window.webkit420 || window.opera) {
            // Safari and Opera need a little back-push :P.
            this.frame.fireEvent('load');
        }
    },
    
    /**
     * @return The HTML contained in the editor.
     */
    getValue: function(){
        return this.content.body.innerHTML;
    },
    
    /**
     * Sets a value to the editor.
     * @param {String} html		HTML string.
     */
    setValue: function(html){
        this.value = html;
        
        // If the editor is fully loaded, update the contents of it.
        if (this.content != null) {
            this.content.body.innerHTML = this.value;
        }
    },
    
    /**
     * Focuses the editor area (iframe with designMode set to "on").
     * By default, it is called after clicking on a button and after the action associated with the button executes.
     */
    focus: function(){
        this.frame.contentWindow.focus();
    },
    
    /**
     * Function used to prepare the editor for the execCommand function.
     */
    restore: function(){
        if (window.ie) {
            if (this.lastSelection) {
                this.lastSelection.select();
            }
        }
    }
});
